#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    int N = 9;//滑块个数
    int sqn = sqrt(N);
    //滑块的设定
    const int a=50;
    const int b=100;
    const int side=100;

    //存储序号
    int *p = new int[N-1];
    for(int i=0;i<N-1;i++)
        p[i]=i+1;

    //序列随机排序
    using std::shuffle;
    std::mt19937 generator(std::time(nullptr));//生成随机数种子
    //打乱顺序
    shuffle(p, p + N - 1, generator);

    //滑块就是按钮
    Block = new QPushButton[N];
    for(int i=0;i<sqn;i++){
        for(int j=0;j<sqn;j++){
            //将按钮控件添加到当前的窗口中
            Block[sqn*i+j].setParent(this);
            //(左边缘，上边缘，宽，高)设置大小
            Block[sqn*i+j].setGeometry(a+side*j,b+side*i,side,side);
            //信号与槽函数
            connect(&Block[sqn*i+j],&QPushButton::clicked,this,[=](){
                this->update(i,j);
            });
            if(!(i == sqn-1 && j == sqn-1))
                Block[sqn*i+j].setText(QString::number(p[sqn*i+j]));
        }
    }

    //存储空滑块下标
    Void = new Coordinate(sqn);


    //记步数
    step = new QLabel(this);
    step->setGeometry(600,200,400,50);
    step->setText("Steps:  "+QString::number(totalSteps));
    step->setFont(QFont("宋体",18,QFont::Bold,true));

    //记时间
    time = new QLabel(this);
    time->setGeometry(600,300,400,50);
    time->setText("Time:   "+QString::number(0));
    time->setFont(QFont("宋体",18,QFont::Bold,true));

    timer = new QTimer(this);
    connect(timer,&QTimer::timeout,this,&MainWindow::timeoutShow);

    //准备开始计时工作
    isBegin = false;
    startTime = new QDateTime;//先分配内存

}

MainWindow::~MainWindow()
{
    delete ui;
}
//更新
void MainWindow::update(int a, int b)
{
    //相邻滑块坐标
    Coordinate *Up = new Coordinate(Void->X()-1,Void->Y(),sqrt(Void->N()));
    Coordinate *Down = new Coordinate(Void->X()+1,Void->Y(),sqrt(Void->N()));
    Coordinate *Left = new Coordinate(Void->X(),Void->Y()-1,sqrt(Void->N()));
    Coordinate *Right = new Coordinate(Void->X(),Void->Y()+1,sqrt(Void->N()));

    //转化到一维数组下的下标
    int n = sqrt(Void->N()) * a + b; //被点击滑块的 单 坐标

    if(n==Up->retIndex()){
        Block[Void->retIndex()].setText(Block[Up->retIndex()].text());
        Block[Up->retIndex()].setText("");
        Void->setIndex(Up->X(),Up->Y());
        totalSteps++;
        step->setText("Steps:  "+QString::number(totalSteps));
        if(!isBegin){
            timer->start();
            *startTime = QDateTime::currentDateTime();
            isBegin = true;
        }
        //更新窗口
        QWidget::update();
    }
    if(n==Down->retIndex()){
        Block[Void->retIndex()].setText(Block[Down->retIndex()].text());
        Block[Down->retIndex()].setText("");
        Void->setIndex(Down->X(),Down->Y());
        totalSteps++;
        step->setText("Steps:  "+QString::number(totalSteps));
        if(!isBegin){
            timer->start();
            *startTime = QDateTime::currentDateTime();
            isBegin = true;
        }
        QWidget::update();
    }
    if(n==Left->retIndex()){
        Block[Void->retIndex()].setText(Block[Left->retIndex()].text());
        Block[Left->retIndex()].setText("");
        Void->setIndex(Left->X(),Left->Y());
        totalSteps++;
        step->setText("Steps:  "+QString::number(totalSteps));
        if(!isBegin){
            timer->start();
            *startTime = QDateTime::currentDateTime();
            isBegin = true;
        }
        QWidget::update();
    }
    if(n==Right->retIndex()){
        Block[Void->retIndex()].setText(Block[Right->retIndex()].text());
        Block[Right->retIndex()].setText("");
        Void->setIndex(Right->X(),Right->Y());
        totalSteps++;
        step->setText("Steps:  "+QString::number(totalSteps));
        if(!isBegin){
            timer->start();
            *startTime = QDateTime::currentDateTime();
            isBegin = true;
        }
        QWidget::update();
    }


    //判断游戏结束
    bool isOver = true;
    for(int i=0;i<Void->N()-1;i++){//除去最后一个滑块
        if(Block[i].text()!=QString::number(i+1)){
            isOver = false;
            break;
        }
    }
    if(isOver){
        timer->stop();
        QMessageBox overWindow;
        overWindow.setText("恭喜你！(≧∇≦)/你赢了~\n总步数："+QString::number(totalSteps));
        overWindow.setWindowTitle("游戏胜利(^o^)");
        overWindow.setFixedSize(100,65);
        overWindow.exec();
    }
}

void MainWindow::timeoutShow()
{
    QDateTime endTime = QDateTime::currentDateTime();
    long long int interval = startTime->secsTo(endTime);
    time->setText("Time:   "+QString::number(interval)+"s");
}
int getInversions(const int puzzle[], int size) {
    int inversions = 0;
    for (int i = 0; i < size; ++i) {
        for (int j = i + 1; j < size; ++j) {
            // 不考虑空格（通常用0表示）
            if (puzzle[i] > 0 && puzzle[j] > 0 && puzzle[i] > puzzle[j]) {
                ++inversions;
            }
        }
    }
    return inversions;
}
int findBlankRowFromBottom(const int puzzle[], int size) {
    int gridSize = static_cast<int>(sqrt(size));
    for (int i = size - 1; i >= 0; --i) {
        if (puzzle[i] == 0) {
            return gridSize - (i / gridSize);
        }
    }
    return -1;  // 应该永远不会到这里
}
bool MainWindow::isSolvable(const int puzzle[]) {
    int length =sizeof(puzzle)/sizeof(puzzle[1]);
    int inversions = getInversions(puzzle, length);
    int blankRowFromBottom = findBlankRowFromBottom(puzzle, length);
    int gridSize = static_cast<int>(sqrt(length));

    // 如果是奇数维度的网格,无解就返回0
    if (gridSize % 2 != 0) {
        return inversions % 2 == 0;
    } else {
        // 如果是偶数维度的网格，无解就返回0
        return (inversions % 2 == 0) == (blankRowFromBottom % 2 != 0);
    }
}


